<?php

namespace Zwwl2016\System;

use Illuminate\Console\Command;

class CheckComments extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'system:repo:checkcomments';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Check comments of all commands';


    private $subUri;


    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }


    /**
     * @output String error_code 错误码;
     * @output String error_message 错误信息;
     * @return bool
     * @throws \ReflectionException
     */
    public function handle()
    {
        $this->subUri = base_path();
        $path = base_path('app/Console/Commands');
        $openDir = opendir($path);
        while ($file = readdir($openDir)){
            if($file != '.' && $file != '..'){
                list($className,$mime) = explode(".",$file);
                if(strstr($file,'common')){
                    continue;
                }
                $content = file_get_contents($path.'/'.$file);
                preg_match("/protected \\$+signature = '[a-zA-Z\_]+(:[a-zA-Z\_]+)+( \\{\S+\\})*';/", $content,$matchSignature);
                if($matchSignature){
                    preg_match("/[a-zA-Z]+(\:[a-zA-Z]+)+/",$matchSignature[0],$match);
                    if($match){
                        $command = $match[0];
                        $class = new \ReflectionClass("App\Console\Commands\\".$className);
                        $comments = $class->getMethod('handle')->getDocComment();
                        preg_match_all('/@input(\s\w+)+((\s\w+)+\s[0-9a-zA-Z\x7f-\xff\_]+\;)+/',$comments,$input);
                        $inputParam = [];
                        foreach($input[0] as $item){
                            if(strpos($item,'Object') > -1){
                                $str = substr($item,strpos($item,'Object')+6);
                                preg_match_all('/(\s\w+)\s[0-9a-zA-Z\x7f-\xff\_]+\;/',$str,$params);
                                $object = [];
                                foreach($params[0] as $param){
                                    $str = str_replace($param,'',$str);
                                    list($key,$description) = explode(' ',trim($param));
                                    $object[trim($key)] = trim(str_replace(";","",$description));
                                }
                                $inputParam[trim($str)] = $object;
                            }elseif(strpos($item,'Array') > -1){
                                $str = substr($item,strpos($item,'Array')+6);
                                preg_match_all('/(\s\w+)\s[0-9a-zA-Z\x7f-\xff\_]+\;/',$str,$params);
                                $array = [];
                                foreach($params[0] as $param){
                                    $str = str_replace($param,'',$str);
                                    list($key,$description) = explode(' ',trim($param));
                                    $array[trim($key)] = trim(str_replace(";","",$description));
                                }
                                $inputParam[trim($str)] = [$array];
                            }elseif(strpos($item,'String') > -1){
                                $str = substr($item,strpos($item,'String')+6);
                                preg_match('/(\s\w+)\s[0-9a-zA-Z\x7f-\xff\_]+\;/',$str,$param);
                                list($key,$description) = explode(' ',trim($param[0]));
                                $inputParam[trim($key)] = trim(str_replace(";","",$description));
                            }elseif(strpos($item,'Bool') > -1){
                                $str = substr($item,strpos($item,'Bool')+4);
                                preg_match('/(\s\w+)\s[0-9a-zA-Z\x7f-\xff\_]+\;/',$str,$param);
                                list($key,$description) = explode(' ',trim($param[0]));
                                $inputParam[trim($key)] = trim(str_replace(";","",$description));
                            }else{
                                $response = ['error_code'=>'40000','error_message'=>'The comments of '.$className.' is not standard'];
                                $this->info(json_encode($response));
                                return false;
                            }
                        }
                        preg_match_all('/@output(\s\w+)+((\s\w+)+\s[0-9a-zA-Z\x7f-\xff\_]+\;)+/',$comments,$output);
                        $outputParam = [];
                        foreach($output[0] as $item){
                            if(strpos($item,'Object') > -1){
                                $str = substr($item,strpos($item,'Object')+6);
                                preg_match_all('/(\s\w+)\s[0-9a-zA-Z\x7f-\xff\_]+\;/',$str,$params);
                                $object = [];
                                foreach($params[0] as $param){
                                    $str = str_replace($param,'',$str);
                                    list($key,$description) = explode(' ',trim($param));
                                    $object[trim($key)] = trim(str_replace(";","",$description));
                                }
                                $outputParam[trim($str)] = $object;
                            }elseif(strpos($item,'Array') > -1){
                                $str = substr($item,strpos($item,'Array')+6);
                                preg_match_all('/(\s\w+)\s[0-9a-zA-Z\x7f-\xff\_]+\;/',$str,$params);
                                $array = [];
                                foreach($params[0] as $param){
                                    $str = str_replace($param,'',$str);
                                    list($key,$description) = explode(' ',trim($param));
                                    $array[trim($key)] = trim(str_replace(";","",$description));
                                }
                                $outputParam[trim($str)] = [$array];
                            }elseif(strpos($item,'String') > -1){
                                $str = substr($item,strpos($item,'String')+6);
                                preg_match('/(\s\w+)\s[0-9a-zA-Z\x7f-\xff\_]+\;/',$str,$param);
                                list($key,$description) = explode(' ',trim($param[0]));
                                $outputParam[trim($key)] = trim(str_replace(";","",$description));
                            }elseif(strpos($item,'Bool') > -1){
                                $str = substr($item,strpos($item,'Bool')+4);;
                                preg_match('/(\s\w+)\s[0-9a-zA-Z\x7f-\xff\_]+\;/',$str,$param);
                                list($key,$description) = explode(' ',trim($param[0]));
                                $outputParam[trim($key)] = trim(str_replace(";","",$description));
                            }else{
                                $response = ['error_code'=>'40000','error_message'=>'The comments of '.$className.' is not standard'];
                                $this->info(json_encode($response));
                                return false;
                            }
                        }
                        preg_match_all('/@dependence(\s+\w+)+(\s+[0-9a-zA-Z\x7f-\xff\_]+\;)+/',$comments,$dependence);
                        $dependenceParam = [];
                        foreach($dependence[0] as $item){
                            list($prefix,$param,$description) = explode(' ',$item);
                            $dependenceParam[$param] = $description;
                        }
                        if(empty($inputParam)){
                            $inputParam = (object)array();
                        }
                        if(empty($outputParam)){
                            $outputParam = (object)array();
                        }
                        if(empty($dependenceParam)){
                            $dependenceParam = (object)array();
                        }
                        $remark = json_encode([$inputParam,$outputParam,$dependenceParam],JSON_UNESCAPED_UNICODE);
                        $endpointHandler = \DB::table('dm_endpoint_handler')->where('key',$command)->first();

                        preg_match("/protected \\$+description = +'[x7f-\xff\-a-z-A-Z\_]+/", $content,$names);
                        $name = str_replace('protected $description = '."'",'',$names[0]);
                        $endpoint = \DB::table('dm_endpoint')->where('enable', '1')->orderBy('id','desc')->value('key');
                        if($endpointHandler){
                            if($endpointHandler->remark != $remark || $endpointHandler->sub_uri != $this->subUri || $endpointHandler->key != $command || $endpointHandler->name != $name || $endpointHandler->endpoint_key != $endpoint){
                                $result = \DB::table('dm_endpoint_handler')->where('key',$command)->update([
                                    'remark' => $remark,
                                    'sub_uri' => $this->subUri,
                                    'key' => $command,
                                    'name' => $name,
                                    'endpoint_key' => $endpoint,
                                ]);
                                if(!$result) {
                                    $response = ['error_code'=>'50000','error_message'=>'Update comments failed'];
                                    $this->info(json_encode($response));
                                    return false;
                                }
                            }
                        }else{
                            $result = \Db::table('dm_endpoint_handler')->insert([
                                'sub_uri' => $this->subUri,
                                'key' => $command,
                                'name' => $name,
                                'endpoint_key' => $endpoint,
                                'remark' => $remark,
                            ]);
                            if(!$result) {
                                $response = ['error_code'=>'50000','error_message'=>'Create command record failed'];
                                $this->info(json_encode($response));
                                break;
                            }
                        }
                    }else{
                        $response = ['error_code'=>'40000','error_message'=>'The signature of '.$className.' is not standard'];
                        $this->info(json_encode($response));
                        return false;
                    }
                }else{
                    $response = ['error_code'=>'40000','error_message'=>$className.' is not standard!'];
                    $this->info(json_encode($response));
                    return false;
                }
            }
        }
        $this->info(json_encode(['error_code'=>'0','error_message'=>'']));
        return true;
    }

    private function generateMapFile($path="")
    {

    }
}
